package com.hp.usage.gr.cli;

import com.hp.siu.collector.rules.RuleException;
import com.hp.siu.logging.Level;
import com.hp.siu.logging.Logger;
import com.hp.siu.utils.Attribute;
import com.hp.siu.utils.Config;
import com.hp.siu.utils.ConfigurationException;
import com.hp.siu.utils.NormalizedMeteredEvent;
import com.hp.usage.gr.GrBaseRule;
import com.hp.usage.nme.AttributeRef;
import com.hp.usage.nme.NME;
import com.hp.usage.nme.NMEMutableArray;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;

/**
 * Created by huxiaoji on 1/28/2016.
 */
public class GRQueryTaskResult extends GrBaseRule{
    private static Logger log_ = Logger.getLogger("com.hp.usage.gr.cli.GRQueryTaskResult", "com.hp.usage.gr.message_catalog");

    public static int MAX_LOG_LENGTH = 1000;

    private String taskId, taskPath, beginLogId, resultCode;
//  RESULT_CODE 0 -- finished success, change status from starting -> paused/stopping -> stopped
//              1 -- finished failed, change status from starting/stopping -> error
//              2 -- still running, do nothing
//              3 -- program failed, do nothing
    @Override
    public void applyRule(NormalizedMeteredEvent nme, NormalizedMeteredEvent normalizedMeteredEvent1) throws RuleException {
        if (log_.isLoggable(Level.DEBUG4)){
            log_.logDebug4("applyRule(" + nme + ")");
        }
        Attribute attr = nme.getAttribute(taskPath);
        if (attr == null) throw new RuleException("TaskPathAttribute is mandatory.");
        String path = attr.toString().trim();
        attr = nme.getAttribute(beginLogId);
        long begin;
        if (attr == null) begin = 0;
        else begin = Long.parseLong(attr.toString());

        NME snme = getSNME(nme);

        File status = new File(path + ".status");
        File log = new File(path + ".log");
        if (!(status.exists() && log.exists())){
            setAttributesInNME(nme, resultCode, "3");
            setResultCode(snme, "4004");
            next(nme, normalizedMeteredEvent1);
            return;
        }

        try {
            boolean hasLog = false;
            BufferedReader logIn = new BufferedReader(new InputStreamReader(new FileInputStream(log)));
            try {
                long count = 0;
                int lc = 0;
                NME response = getResponse(snme);
                AttributeRef attrRef = response.getAttributeRef("logList");
                NME ll = createEmptyNME("gr:LogListType");
                response.setStruct(attrRef, ll);
                NMEMutableArray array = createNewArray(MAX_LOG_LENGTH);
                attrRef = ll.getAttributeRef("record");
                ll.setArray(attrRef, array);

                while (logIn.ready()) {
                    String line = logIn.readLine();
                    count++;
                    if (count > begin && lc < MAX_LOG_LENGTH) {
                        lc++;
                        NME r = createEmptyNME("gr:recordLogRecordType");
                        setLong(r, "id", String.valueOf(count));
                        String[] var = splitLog(line);
                        setString(r, "timestamp", var[0]);
                        setString(r, "message", var[1]);

                        array.add(r);
                    } else {
                        break;
                    }
                }

                if (logIn.ready()){
                    hasLog = true;
                }
            } finally {
                logIn.close();
            }

            BufferedReader statusIn = new BufferedReader(new InputStreamReader(new FileInputStream(status)));
            try{
                String line = statusIn.readLine();
//                0 - finished 1 - command error 2 - execute failed 3 - execute abort 4 - task running
                int taskStatus = Integer.parseInt(line);
                if (taskStatus == 1){
                    setAttributesInNME(nme, resultCode, "1");
                    setResultCode(snme, "4011");
                } else if (taskStatus == 2 || taskStatus == 3){
                    setAttributesInNME(nme, resultCode, "1");
                    if (hasLog)
                        setResultCode(snme, "4021");
                    else
                        setResultCode(snme, "4020");
                } else if (taskStatus == 4){
                    setAttributesInNME(nme, resultCode, "2");
                    setResultCode(snme, "2021");
                } else if (taskStatus == 0){
                    if (hasLog){
                        setResultCode(snme, "2020");
                    } else {
                        setResultCode(snme, "2001");
                    }
                    setAttributesInNME(nme, resultCode, "0");
                }
            } finally {
                statusIn.close();
            }
        } catch (Exception e){
            log_.logWarning(e.getMessage(), e);
            setAttributesInNME(nme, resultCode, "3");
            setResultCode(snme, "4011");
            return;
        }

        next(nme, normalizedMeteredEvent1);
    }

    private String[] splitLog(String message){
        return new String[]{"date", message};
    }

    @Override
    public void configure(Config config) throws ConfigurationException {
        taskId = config.getAttributeAsString("TaskIdAttribute");
        taskPath = config.getAttributeAsString("TaskPathAttribute");
        beginLogId = config.getAttributeAsString("BeginLogIdAttribute");
        resultCode = config.getAttributeAsString("ResultAttribute");
    }
}
